package com.company.ext;

import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/*
   拓展
   BeanPostProcessor bean的后置处理器，bean创建对象初始化前后进行拦截工作
   BeanFactoryPostProcessor beanFactory的后置处理器
      再BeanFactory标准初始化之后调用，所有的bean定义已经保存加载到beanFactory，但是bean的实例还未创建

   1 ioc容器创建对象
   2 invokeBeanFactoryPostProcessor（beanFactory）执行BeanFactoryPostProcessor
      如何找到所有的BeanFactoryPostProcessor并执行他们的方法
        1 直接在BeanFactory找到所有类型是BeanFactoryPostProcessor的组件，并执行他们的方法
        2 在初始化创建其他组件前面执行

    BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor
        postProcessorBeanDefinitionRegistry();
        在所有Bean定义信息将要被加载，bean实例还没创建

        优先于BeanFactoryPostProcessor
        利用BeanDefinitionRegistryPostProcessor给容器在额外添加一些组件

   原理
      1 ioc 创建对象
      2 refresh（）----》invokeBeanFactoryPostProcessor（beanFactory）；
      3 先从容器中获取所有的BeanDefinitionRegistryPostProcessor组件
          1 依次触发所有的postProcessorBeanDefinitionRegistry
          2 再来触发postProcessorBeanFactory()

      4 再来从容器中找到BeanFactoryPostProcessor组件，然后依次触发postProcessorBeanFactory()方法

  3 ApplicationListener 监听容器中发布的事件，时间驱动模型的开发
       public interface ApplicationListener<E extends ApplicationEvent>
        监听ApplicationEvent 及其下面的子事件
    步骤
       1 写一个监听器来监听某个事件（ApplicationEvent及其子类）或@EventListener
              @EventListener
                  原理 使用EventListenerMethodProcessor处理器解析方法上的@EventListener
                  实现了接口SmartInitializingSingleton
                    1 ioc容器创建对象并刷新refresh
                    2 finishBeanFactoryInitiazation（beanFactory）初始化剩下的单实例bean
                        1 先创建所有的单实例bean，getBean（）
                        2 获取所有创建好的单实例bean，判断是否是SmartInitializingSingleton类型的，
                          如果是就调用afterSingletonInstantiated（）；
       2 把监听器加入到容器中
       3 只要容器中有相关事件的发布，我们就能监听到事件
              ContextRefreshedEvent 容器刷新完成（所有bean都创建完成）会发布这个事件
              ContextClosedEvent    关闭容器会发布这个事件
       4 发布事件
               applicationContext.publishEvent
       1   ContextRefreshedEvent
              1 容器创建对象时候 ，refresh
              2 finishRefresh（） 容器刷新完成
              3 publishEvent（new ContextRefreshedEvent（this））
                   事件发布流程
                      1 获取事件的多播器（派发器） getApplicationEventMulticaster（）
                      2 multicastEvent派发事件
                      3 获取到所有的ApplicationListener
                          for（final ApplicationListener<?>listener: getApplicationListeners(event,type)）
                          1 如果Executor 可以支持异步派发
                             Executor executor = getTaskExecutor（）；
                          2 否则同步的方法直接执行listener方法，invokeListener（listener，event）
                            拿到listener回调onApplicationEvent方法
    事件多播器
      1 容器创建对象，refresh（）
      2 initApplicationEventMulticaster（），初始化ApplicationEventMulticaster
              1 先去容器找有没有id="ApplicationEventMulticaster"的组件
              2 如果没有this.applicationEventMulticaster = new SimpleApplicationEventMulticaster（beanFactory）
                并且加入到容器中，我们就可以在其他组件要派发事件，自动注入这个applicationEventMulticaster

     容器中有哪些监听器
     1 容器创建对象 refresh
     2 registerListener（）
       从容器中拿到所有的监听器，把他们注册到applicationEventMulticaster中
       String[]listerBeanNames = getBeanNamesForType（ApplicationListener.class,true,false）
       将lister注册到ApplicationEventMulticaster
       getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName)



 */
@Configuration
@ComponentScan("com.company")
public class ExtConfig {


}
